package org.teachertools.web.controller;

import java.util.LinkedList;
import java.util.List;

import javax.annotation.Resource;

import org.apache.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
import org.teachertools.data.Matiere;
import org.teachertools.services.CategorieService;
import org.teachertools.services.MatiereService;
import org.teachertools.services.exception.ServiceException;
import org.teachertools.web.dto.MatiereDTO;
import org.teachertools.web.forms.MatiereForm;
import org.teachertools.web.forms.MatiereFormMapping;
import org.teachertools.web.jsonview.JsonView;

@Controller
@RequestMapping("/matieres/*")
public class MatiereController {

    private static final Logger logger = Logger.getLogger(MatiereController.class);

    @Resource
    private CategorieService categorieService;
    @Resource
    private MatiereService matiereService;

    @RequestMapping("show")
    public String searchMatieres(ModelMap model, @ModelAttribute MatiereForm matiere) throws ServiceException {
        logger.debug("method searchMatieres called in the controller");
        List<Matiere> matieres = this.matiereService.searchByExample(MatiereFormMapping.mappingFormToDTO(matiere));
        if (logger.isDebugEnabled()) {
            logger.debug("Found " + matieres.size() + " matieres");
        }
        model.addAttribute("categories", this.categorieService.getList());
        model.addAttribute("matieres", this.matiereService.getList());
        model.addAttribute("matieres", matieres);
        return "matieres/show";
    }

    @RequestMapping("ajax/show")
    public String ajaxSearchMatieres(ModelMap model, @ModelAttribute MatiereForm matiere) throws ServiceException {
        logger.debug("Ajax Invocation of searchMatieres");
        searchMatieres(model, matiere);
        return "matieres/results";
    }

    @RequestMapping(value = "add", method = RequestMethod.GET)
    public String prepareAddMatiere(ModelMap model) throws ServiceException {
        logger.debug("method prepareAddMatiere called in the controller");
        model.addAttribute("matiere", new MatiereForm());
        return "matieres/view";
    }

    @RequestMapping(value = "add", method = RequestMethod.POST)
    public String addMatiere(ModelMap model, @ModelAttribute MatiereForm matiere, BindingResult result)
            throws ServiceException {
        logger.debug("method addMatiere called in the controller");
        // TODO Validate Matiere Form
        // new MatiereValidator().validate(matiere, result);
        if (result.hasErrors()) {
            logger.debug("Validation has errors, no action");
            return "matieres/view";
        } else {
            this.matiereService.save(MatiereFormMapping.mappingFormToDTO(matiere));
        }
        LinkedList<String> messages = new LinkedList<String>();
        messages.add("success.save");
        model.addAttribute("messages", messages);
        return searchMatieres(model, new MatiereForm());
    }

    @RequestMapping(value = "view/{id}", method = RequestMethod.GET)
    public String viewMatiere(ModelMap model, @PathVariable("id") long matiereId) throws ServiceException {
        logger.debug("method viewMatiere called in the controller");
        model.addAttribute("matiere", this.matiereService.get(matiereId));
        return "matieres/view";
    }

    @RequestMapping(value = "update", method = RequestMethod.POST)
    public String updateMatiere(ModelMap model, @ModelAttribute MatiereForm matiere, BindingResult result)
            throws ServiceException {
        logger.debug("method updateMatiere called in the controller");
        // TODO Validate Matiere Form
        // new MatiereValidator().validate(matiere, result);
        Matiere loadedMatiere = this.matiereService.get(matiere.getId());
        loadedMatiere.setNom(matiere.getNom());
        this.matiereService.update(loadedMatiere);

        LinkedList<String> messages = new LinkedList<String>();
        messages.add("success.save");
        model.addAttribute("messages", messages);
        return viewMatiere(model, matiere.getId());
    }

    @RequestMapping(value = "delete/{id}", method = RequestMethod.GET)
    public String deleteMatiere(ModelMap model, @PathVariable("id") long matiereId) throws ServiceException {
        logger.debug("method deleteMatiere called in the controller");
        this.matiereService.deleteById(matiereId);
        return searchMatieres(model, new MatiereForm());
    }

    @RequestMapping(value = "category/{id}/list", method = RequestMethod.GET)
    public ModelAndView getMatiereForCategory(@PathVariable("id") long categoryId) throws ServiceException {
        logger.debug("method getMatiereForCategory called in the controller");
        List<Matiere> matieres = this.matiereService.getMatiereForCategorieId(categoryId);
        List<MatiereDTO> matiereForms = new LinkedList<MatiereDTO>();
        for (Matiere matiere : matieres) {
            MatiereDTO matiereDto = new MatiereDTO();
            matiereDto.setId(matiere.getId());
            matiereDto.setNom(matiere.getNom());
            matiereForms.add(matiereDto);
        }
        ModelAndView model = new ModelAndView(new JsonView());
        model.addObject("matieres", matiereForms);
        return model;
    }
}
